package dd.lo.chapter2;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfByte;
import org.opencv.core.Size;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

import java.io.ByteArrayInputStream;

/**
 * 对应程序示例
 * Example 2-5. Loading and then smoothing an image before it is displayed on the screen
 * Example 2-6. Using cv::pyrDown() to create a new image that is half the width and height of the input image
 * Example 2-7. The Canny edge detector writes its output to a single-channel (grayscale) image
 */
public class Example4 extends Application {
    public static void main(String[] args) {
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
        launch(args);
    }

    @Override
    public void start(Stage stage) {
        //读取一张图片
        Mat srcImg = Imgcodecs.imread("/Users/kwok/Downloads/男女骑友.png", Imgcodecs.IMREAD_UNCHANGED);
        if (srcImg.empty()) {
            throw new RuntimeException("图片读取失败");
        }
        //执行例子中提到的高斯模糊，例子中模糊了2次
        Mat gaussianBlurOut = new Mat();
        Imgproc.GaussianBlur(srcImg, gaussianBlurOut, new Size(5, 5), 3, 3);
        Imgproc.GaussianBlur(gaussianBlurOut, gaussianBlurOut, new Size(5, 5), 3, 3);
        Mat pyrDownOut = new Mat();
        Imgproc.pyrDown(srcImg, pyrDownOut);
        Mat grayOut = new Mat();
        Imgproc.cvtColor(srcImg, grayOut, Imgproc.COLOR_BGR2GRAY);
        Mat cannyOut = new Mat();
        Imgproc.Canny(grayOut, cannyOut, 10, 100, 3, true);
        //将原图放到imageView中展示
        MatOfByte buffer = new MatOfByte();
        Imgcodecs.imencode(".jpeg", srcImg, buffer);
        ImageView imageView = new ImageView();
        imageView.setImage(new Image(new ByteArrayInputStream(buffer.toArray())));
        //imageView放到一个pane的中间
        BorderPane root = new BorderPane();
        root.setCenter(imageView);
        Scene scene = new Scene(root, srcImg.width(), srcImg.height());
        scene.setOnKeyReleased(keyEvent -> {
            //按下esc可以关闭程序
            if (KeyCode.ESCAPE == keyEvent.getCode()) {
                stage.close();
            }
        });
        stage.setScene(scene);
        stage.setTitle("Example4-Origin");
        stage.setResizable(false);
        stage.show();
        Platform.runLater(() -> showImgNewWindow(gaussianBlurOut, "Example4-Gaussian Blur"));
        Platform.runLater(() -> showImgNewWindow(pyrDownOut, "Example4-Gaussian Pyramid Downsample"));
        Platform.runLater(() -> showImgNewWindow(grayOut, "Example4-Gray"));
        Platform.runLater(() -> showImgNewWindow(cannyOut, "Example4-Canny"));
    }

    private void showImgNewWindow(Mat img, String windowName) {
        MatOfByte buffer = new MatOfByte();
        Imgcodecs.imencode(".jpeg", img, buffer);
        ImageView imageView = new ImageView();
        imageView.setImage(new Image(new ByteArrayInputStream(buffer.toArray())));
        BorderPane root = new BorderPane();
        root.setCenter(imageView);
        Scene scene = new Scene(root, img.width(), img.height());
        Stage stage = new Stage();
        stage.setScene(scene);
        stage.setTitle(windowName);
        stage.setResizable(false);
        stage.show();
    }
}
